package com.mo.tools.sequence;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicLong;

/**
 * @name: SequenceGenerator
 * @description:
 * @author: Yang Xingfu
 * @date: 2019-12-18 15:56
 **/
public class SequenceGenerator {

    private static Logger log = LoggerFactory.getLogger(SequenceGenerator.class);

    private static String ZERO = "0";

    /**
     * 机器号
     */
    private String machineNumber;

    /**
     * 服务号
     */
    private String serviceNumber;

    /**
     * 序列长度，不足补零
     */
    private volatile int sequenceLength;

    /**
     * code前缀
     */
    private String prefix;

    /**
     * 自增数
     */
    private volatile AtomicLong atomicLong;

    /**
     * 生成的序列
     */
    public String sequence;

    /**
     * 生成的编码
     */
    public String code;

    /**
     * 回调函数
     */
    private ISequenceCallBack callBack;

    public SequenceGenerator(String sequence, String code) {
        this.sequence = sequence;
        this.code = code;
    }

    public SequenceGenerator(String machineNumber, String serviceNumber, int sequenceLength, String prefix, AtomicLong atomicLong, ISequenceCallBack callBack) {
        this.machineNumber = machineNumber;
        this.serviceNumber = serviceNumber;
        this.sequenceLength = sequenceLength;
        this.prefix = prefix;
        this.atomicLong = atomicLong;
        this.callBack = callBack;
    }

    /**
     * 生成序列，长度不足前缀补0
     *
     * @return
     * @throws Exception
     */
    public synchronized SequenceGenerator generatorSequence() throws Exception {

        String sequenceStr = null;

        try {

            if (machineNumber == null) {
                log.error("序列生成失败，机器码不能为空");
                throw new Exception("序列生成失败，机器码不能为空");
            }

            long max = (long) Math.floor(Math.pow(10, sequenceLength));
            String sequenceMax = String.valueOf(max);

            if (atomicLong == null) {
                atomicLong = new AtomicLong(Integer.valueOf(ZERO));
            }
            long sequenceLong = atomicLong.incrementAndGet();
            sequenceStr = String.valueOf(sequenceLong);
            if (sequenceStr.equals(sequenceMax)) {
                log.error("序列已达到最大值，请调整序列长度");
                throw new Exception("序列已达到最大值，请调整序列长度");
            }

        } catch (Exception e) {
            log.error("生成序列错误");
            System.exit(1);
        }

        return generateCode(sequenceStr);


    }

    /**
     * 生成编码，并执行回调
     *
     * @param sequence
     * @return
     */
    public SequenceGenerator generateCode(String sequence) {

        String code = null;

        StringBuilder stringBuilder = new StringBuilder();

        StringBuilder newSequence = new StringBuilder();
        ;

        if (prefix != null) {
            stringBuilder.append(prefix);
        }


        if (serviceNumber != null) {
            stringBuilder.append(serviceNumber);
        }

        if (machineNumber != null) {
            stringBuilder.append(machineNumber);
        }

        for (int i = 0; i < sequenceLength - sequence.length(); i++) {

            newSequence.append(ZERO);
        }

        if (newSequence != null) {
            sequence = newSequence.append(sequence).toString();
            stringBuilder.append(sequence);
        }

        code = stringBuilder.toString();
        this.sequence = sequence;
        this.code = code;

        if (code != null && callBack != null) {
            callBack.execute(this);
        }

        return new SequenceGenerator(this.sequence, this.code);
    }

}
